﻿using System;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Win32;

namespace Warl
{
    public partial class Main : Form
    {
        private Profile[] Profiles;
        private string serverIniPath;
        // thread stuff
        private PingThread pingThread;
        public delegate void addServerDelegate(int uid, string name, string server, long ping, bool refresh);
        private delegate void loadServersFinishedDelegate();
        private delegate void loadPingThreadDelegate();

        public Main()
        {
            InitializeComponent();
        }

        #region Form Controls

        private void Main_Load(object sender, EventArgs e)
        {
            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
            startInfo.FileName = "Updater.exe";
            startInfo.Arguments = "-id 1 -version " + Application.ProductVersion;
            startInfo.WorkingDirectory = Application.StartupPath;
            System.Diagnostics.Process proc = System.Diagnostics.Process.Start(startInfo);
            //
            //
            Settings.setPath(Application.StartupPath);
            Settings.setProfile("Default");
            //
            serverIniPath = Application.StartupPath + "\\Servers.ini";
            if (File.Exists(serverIniPath))
                new Thread(new ParameterizedThreadStart(loadServers)).Start();
            else { File.Create(serverIniPath); }
            //
            loadProfiles(false);
            comboBox1.SelectedIndex = 0;
            //
            if (!proc.WaitForExit(10000)) { proc.Kill(); MessageBox.Show("Updater Utility timed out"); }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ListViewItem item = getSelectedItem();
            if (item == null)
                showError(2, "You must select which server you want to play on.");
            else
            {
                setRealmlist("set realmlist " + item.SubItems[2].Text); //write realmlist
                System.Diagnostics.Process.Start(findWoWPath() + "Wow.exe"); // start wow
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            new Add_Server(this, listView1.Items.Count + 1).Show();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            ListViewItem item = getSelectedItem();
            if (item != null)
            {
                new IniFile(serverIniPath).DeleteSection("uid_" + item.SubItems[0].Text);
                item.Remove();
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            new SettingsForm(this).Show();
        }

        private void button5_Click(object sender, EventArgs e)
        {
            new Add_Profile(this).Show();
        }

        private void button6_Click(object sender, EventArgs e)
        {
            new SmartSense().Show();
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            Settings.setProfile(getActiveProfile().Name);
        }

        private void Main_FormClosing(object sender, FormClosingEventArgs e)
        {
            Environment.Exit(0);
        }

        #endregion

        #region Functions

        public void setRealmlist(string rl)
        {
            File.WriteAllText(findRealmlistPath(true) + "realmlist.wtf", rl);
        }

        public string findWoWPath()
        {
            if (!String.IsNullOrEmpty(Settings.wowPath)) { return Settings.wowPath; }
            string[] paths = smartSenseSearch.quickSearch();
            if (paths.Length > 1)
            {
                if (MessageBox.Show("A quick search of your computer has showed up multiple installs of World of Warcraft. Would you like to visit SmartSense to designate which one you would like to use?", "Warl", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    new SmartSense().ShowDialog();
                    return Settings.wowPath;
                }
                return null;
            }
            else
            {
                Settings.wowPath = paths[0];
                return paths[0];
            }
        }

        public string findRealmlistPath(bool checkIni)
        {
            if (!String.IsNullOrEmpty(Settings.realmlistPath)) { return Settings.realmlistPath; }
            return smartSenseSearch.realmlistSearch(findWoWPath());
        }

        public void addProfile(string name)
        {
            File.Create(Application.StartupPath + "\\Profiles\\" + name + ".ini");
            comboBox1.Items.AddRange(new Object[] { name });
            loadProfiles(true);
        }

        private void loadProfiles(bool cacheRefresh)
        {
            string[] _profiles = Directory.GetFiles(Application.StartupPath + "\\Profiles\\");
            Profiles = new Profile[_profiles.Length];
            int i = 0;
            foreach (string _profile in _profiles)
            {
                string name = _profile.Remove(0, _profile.LastIndexOf("\\") + 1);
                name = name.Replace(".ini", "");
                // Settings function that loads the correct profile ini
                Settings.setProfile(name);
                // store the Profile in an array so we don't have to load so much
                Profiles[i] = new Profile(i, name, Settings.wowPath, Settings.realmlistPath);
                // add Profile to combo box
                if (!cacheRefresh) { comboBox1.Items.AddRange(new Object[] { name }); }
                // increase counter
                i++;
            }
        }

        private Profile getActiveProfile()
        {
            return Profiles[comboBox1.SelectedIndex];
        }

        private ListViewItem getSelectedItem()
        {
            if (listView1.SelectedItems.Count >= 1)
            {
                return listView1.SelectedItems[0];
            }
            else { return null; }
        }

        public void showError(int lvl, string error)
        {
            if ((lvl == 1) && (Settings.debugLvl >= 3))
            {
                MessageBox.Show("DEVELOPER DEBUG. This is normal. Error: " + error);
            }
            else if ((lvl == 2) && (Settings.debugLvl >= 2))
            {
                MessageBox.Show("Error: " + error);
            }
            else if ((lvl == 3) && (Settings.debugLvl >= 1))
            {
                MessageBox.Show("CRITICAL ERROR. Application is now unstable. Prepare to see some freaky shit. Error: " + error);
            }
        }

        #endregion

        #region Thread Workers

        private void loadServers(object obj)
        {
            IniFile loadIni = new IniFile(System.Windows.Forms.Application.StartupPath + "\\servers.ini");
            string[] servers = loadIni.GetSectionNames();
            foreach (string server in servers)
            {
                addServer(Convert.ToInt32(server.Replace("uid_", "")), loadIni.GetString(server, "name", ""), loadIni.GetString(server, "server", ""), 0, false);
            }
            pingThread = new PingThread(this);
            loadPingThread();
        }

        public void addServer(int uid, string name, string server, long ping, bool refresh = true)
        {
            if (InvokeRequired)
            {
                BeginInvoke(new addServerDelegate(addServer), new object[] { uid, name, server, ping, refresh });
                return;
            }
            //
            IniFile loadIni = new IniFile(System.Windows.Forms.Application.StartupPath + "\\servers.ini");
            bool alreadyAdded = false;
            foreach (ListViewItem item in listView1.Items)
            {
                if (item.SubItems[0].Text == uid.ToString())
                {
                    alreadyAdded = true;
                    //
                    if (!String.IsNullOrEmpty(name))
                    {
                        item.SubItems[1].Text = name;
                        loadIni.WriteValue("uid_" + uid.ToString(), "name", name);
                    }
                    if (!String.IsNullOrEmpty(server))
                    {
                        item.SubItems[2].Text = server;
                        loadIni.WriteValue("uid_" + uid.ToString(), "server", server);
                    }
                    if (ping == 0)
                    {
                        item.SubItems[3].Text = "Offline";
                        item.SubItems[4].Text = "0ms";
                    }
                    else if (!String.IsNullOrEmpty(ping.ToString()))
                    {
                        item.SubItems[3].Text = "Online";
                        item.SubItems[4].Text = ping.ToString() + "ms";
                    }
                }
            }
            //
            if (!alreadyAdded)
            {
                ListViewItem item = new ListViewItem(new[] { uid.ToString(), name, server, (ping == 0 ? "Offline" : "Online"), ping.ToString() + "ms" });
                listView1.Items.Add(item);
                //
                loadIni.WriteValue("uid_" + uid.ToString(), "name", name);
                loadIni.WriteValue("uid_" + uid.ToString(), "server", server);
            }
            if (refresh) { loadPingThread(); }
        }

        private void loadPingThread()
        {
            if (InvokeRequired)
            {
                BeginInvoke(new loadPingThreadDelegate(loadPingThread), new object[] { });
                return;
            }
            //
            string[,] servers = new string[listView1.Items.Count, 2];
            int i = 0;
            foreach (ListViewItem item in listView1.Items)
            {
                servers[i, 0] = item.SubItems[0].Text;
                servers[i, 1] = item.SubItems[2].Text;
                i++;
            }
            pingThread.recieveUpdate(servers);
        }

        #endregion
    }

    #region Profile

    public class Profile
    {
        private int _i;
        private string _name;
        private string _wowPath;
        private string _realmlistPath;

        public Profile(int i_, string name_, string wowPath_, string realmlistPath_)
        {
            this._i = i_;
            this._name = name_;
            this._wowPath = wowPath_;
            this._realmlistPath = realmlistPath_;
        }

        public int I
        {
            get { return _i; }
        }

        public string Name
        {
            get { return _name; }
        }

        public string wowPath
        {
            get { return _wowPath; }
        }

        public string realmlistPath
        {
            get { return _realmlistPath; }
        }
    }

    #endregion
}
